package utils

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"
)

// GenUploadPath 生成文件上传路径
func GenUploadPath(basePath, filename string, isImg bool) (string, error) {
	now := time.Now()
	dir := fmt.Sprintf("%s/%d/%d", basePath, now.Year(), now.Month())
	// os.Stat(dir) 接受一个路径参数 dir，返回一个 os.FileInfo 结构体和一个 error 对象
	// 若路径有效，则 error 为 nil，os.FileInfo 包含元数据。
	// 若路径不存在或不可访问，则返回 error 描述具体问题（如 os.ErrNotExist）。
	_, err := os.Stat(dir)
	if err != nil {
		// 会一次性创建 dir 参数指定的所有目录层级。如果路径中的中间目录不存在，函数会自动创建这些父目录
		//示例：若 dir 是 a/b/c，即使 a 和 b 不存在，函数也会自动创建这三级目录。
		err = os.MkdirAll(dir, 0755)
		if err != nil {
			return "", fmt.Errorf("创建上传文件夹出现错误：%v", err)
		}
	}
	// 设置文件扩展名
	var fileExt string
	if isImg {
		fileExt = GetImgExt(filename)
	} else {
		fileExt = filepath.Ext(filename)
	}
	// 返回文件上传路径
	// now.UnixMicro()，用于获取当前时间的微秒级 Unix 时间戳（从 1970 年 1 月 1 日 UTC 到当前时间的微秒数）。
	return fmt.Sprintf("%s/%d%s", dir, now.UnixMicro(), fileExt), nil
}

// GenUploadUrl 生成上传文件的 URL
// basePath = "/var/www/data"
// baseUrl  = "https://example.com/data"
// filePath = "/var/www/data/images/pic.jpg"
// 输出："https://example.com/data/images/pic.jpg"
func GenUploadUrl(basePath, baseUrl string, filepath string) string {
	// 使用 strings.Replace 将 filePath 中首次出现的 basePath 替换为 baseUrl。
	// n=1 表示仅替换第一个匹配项，避免多次替换导致路径错误
	return strings.Replace(filepath, basePath, baseUrl, 1)
}

// DownloadFile 下载文件，fileURL文件链接 filepath文件下载位置  proxy 代理服务器地址
func DownloadFile(fileURL string, filepath string, proxy string) error {
	var client *http.Client
	if proxy == "" {
		client = http.DefaultClient
	} else {
		// 将字符串格式的代理地址（如 http://proxy.example.com:8080）解析为 *url.URL 结构体
		proxyURL, _ := url.Parse(proxy)
		client = &http.Client{
			Transport: &http.Transport{
				Proxy: http.ProxyURL(proxyURL), // Proxy: http.ProxyURL(proxyURL) 表示所有请求均通过该代理服务器中转
			},
		}
	}
	// 创建一个自定义的HTTP请求对象
	req, err := http.NewRequest("GET", fileURL, nil)
	if err != nil {
		return err
	}
	//  执行HTTP请求，并获取服务器响应
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	// 创建文件
	file, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer file.Close()
	// http请求的响应，写入到文件中
	_, err = io.Copy(file, resp.Body)
	if err != nil {
		return err
	}
	return nil
}

// GetImgExt 获取图片文件扩展名
func GetImgExt(filename string) string {
	ext := filepath.Ext(filename)
	if ext == "" {
		ext = ".png"
	}
	return ext
}

// ExtractImgURLs 从文本中提取图片URL地址
func ExtractImgURLs(text string) []string {
	re := regexp.MustCompile(`(http[s]?:\/\/.*?\.(?:png|jpg|jpeg|gif))`)
	matches := re.FindAllStringSubmatch(text, 10)
	urls := make([]string, 0)
	if len(matches) > 0 {
		for _, m := range matches {
			urls = append(urls, m[1])
		}
	}
	return urls
}

// ExtractFileURLs 从文本中提取特定格式的URL
// text := "下载文档：http://a.com/doc.pdf 或 https://b.com/sheet.xlsx"
// urls := ExtractFileURLs(text)
// 输出：["http://a.com/doc.pdf", "https://b.com/sheet.xlsx"]
func ExtractFileURLs(text string) []string {
	// http[s]?：匹配 http 或 https 协议头
	// .*?：非贪婪匹配任意字符，直到遇到文件扩展名
	// MustCompile 预编译正则表达式提升性能（尤其需多次调用时）
	re := regexp.MustCompile(`(http[s]?:\/\/.*\.(?:docx?|pdf|pptx?|xlsx?|txt))`)
	// 返回所有子匹配结果（含捕获组），而 FindAllString 仅返回完整匹配
	// 10 表示最多提取10个URL（避免内存溢出）
	matches := re.FindAllStringSubmatch(text, 10)
	urls := make([]string, 0)
	if len(matches) > 0 {
		for _, m := range matches {
			urls = append(urls, m[1])
		}
	}
	return urls
}
